home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Graphics / Misc / NeXTcontour_1.7 / Source / ContourView.m < prev    next >
Encoding:
Text File  |  1995-06-12  |  16.9 KB  |  642 lines

  1.  
  2. /* Generated by Interface Builder */
  3.  
  4. #import "defs.h"
  5. #import "ContourView.h"
  6. #import <appkit/SavePanel.h>
  7. #import <appkit/color.h>
  8. #import <appkit/PrintPanel.h>
  9. #import <appkit/Button.h>
  10. #import <appkit/Pasteboard.h>
  11. extern int contour_(int *jdim, int *kdim, int *nj, int *nk, 
  12.             float *x, float *y, float *f, int *ncont, float *acont,
  13.             float *ppxunit, float *ppyunit, int *colorMap);
  14.  
  15. @implementation ContourView
  16.  
  17. - (BOOL) acceptsFirstMouse { return YES;}    /* grab that mouse down event! */
  18.  
  19. - clear:sender
  20. {
  21.   NXEraseRect(&bounds);
  22.   NXSetColor([contourParam provideBackGroundColor]);
  23.   NXRectFill(&bounds);
  24.   return self;
  25. }
  26.  
  27.  
  28. - setDrawColor:(float) color
  29. {
  30.   PSsetgray(color);
  31.   return self;
  32. }
  33.  
  34. - drawSelf: (const NXRect *)rects :(int)rectCount{
  35.  
  36.   BOOL functionDraw = [contourParam doDrawFunction];
  37.   BOOL gridDraw     = [contourParam doDrawGrid];
  38.   BOOL clearPlot    = [contourParam doClearPlot];
  39.   float  xmin = [contourParam provideXmin];
  40.   float  xmax = [contourParam provideXmax];
  41.   float  ymin = [contourParam provideYmin];
  42.   float  ymax = [contourParam provideYmax];
  43.   const char * maintitle = [contourParam provideMainTitle];
  44.   const char * functiontitle = [contourParam provideFunctionTitle];
  45.   const char * xtitle = "x";
  46.   const char * ytitle = "y";
  47.   char unitLabel[40];
  48.   id titleFont, labelFont;
  49.   float   xwid, yhgt=14.0;
  50.   float xsave;
  51.   float pattern0[] = {};    /* solid      */
  52.   int   viewChoice =   [contourParam provideViewingChoice:self];
  53.   int   viewPoint  =   [contourParam provideViewPoint:self];
  54.   float h,s,br;
  55.   int inc_cont,icont,count_cont;
  56.   int number_of_contours;    /* the number of contour levels */
  57.   float *contour_levels;    /* the contour level values */
  58.   NXColor color;
  59.   int lineColor;
  60.  
  61.   lineColor =  [contourParam provideContourLineColor];
  62.  
  63.   if(clearPlot)[self clear:self];
  64.  
  65.   NXSetColor([contourParam provideForeGroundColor]);
  66.  
  67.   if ([contourParam shouldChangeTitleFont]) {
  68.     newTitleFont =
  69.       [theFontManager convertFont:[theFontManager selFont]];
  70.   }
  71.  
  72.   if (newTitleFont) {
  73.     titleFont = [Font newFont:[newTitleFont name] 
  74.            size:[newTitleFont pointSize]
  75.            style:[newTitleFont style]
  76.            matrix:NX_IDENTITYMATRIX];
  77.     yhgt = [newTitleFont pointSize];
  78.   }
  79.   else {
  80.     titleFont =
  81.       [Font newFont:"Helvetica" size:14.0 style:0 matrix:NX_IDENTITYMATRIX];
  82.     yhgt = 14.0;
  83.   }
  84.   [titleFont set];
  85.  
  86.   xwid = [titleFont getWidthOf:maintitle];
  87.  
  88.   PSmoveto(XOFFSET/4.0 + (bounds.size.width - xwid)/2.0, 
  89.        bounds.size.height - 2.0 - yhgt);
  90.   PSshow((char *)maintitle);
  91.  
  92.   if([contourParam shouldShowXYLabels]){
  93.  
  94.     xwid = [titleFont getWidthOf:functiontitle];
  95.  
  96.     PSmoveto(bounds.size.width-xwid-18.,
  97.            bounds.size.height-40.0);
  98.     PSshow((char *)functiontitle);
  99.  
  100.  
  101.     switch(viewChoice){
  102.  
  103.     case 0:
  104.       xtitle = "x";
  105.       ytitle = "y";
  106.       break;
  107.     case 1:
  108.       xtitle = "x";
  109.       ytitle = "z";
  110.       break;
  111.     case 2:
  112.       xtitle = "y";
  113.       ytitle = "z";
  114.       break;
  115.     case 3:
  116.       xtitle = "i";
  117.       ytitle = "j";
  118.       break;
  119.     case 4:
  120.       xtitle = "y";
  121.       ytitle = "x";
  122.       break;
  123.     case 5:
  124.       xtitle = "z";
  125.       ytitle = "x";
  126.       break;
  127.     case 6:
  128.       xtitle = "z";
  129.       ytitle = "y";
  130.       break;
  131.     }
  132.  
  133.     xwid = [titleFont getWidthOf:xtitle];
  134.  
  135.     PSmoveto(XOFFSET/4.0 + (bounds.size.width - xwid)/2.0, 
  136.          (bounds.origin.y + 10.0));
  137.     PSshow((char *)xtitle);
  138.  
  139.     xwid = [titleFont getWidthOf:ytitle];
  140.     yhgt = 10.0;
  141.     PSmoveto((bounds.origin.x + 10.0 + yhgt), 
  142.          YOFFSET/4.0 + (bounds.size.height - xwid)/2.0);
  143.  
  144.     PSgsave();
  145.     PSrotate(90.0);
  146.     PSshow((char *)ytitle);
  147.     PSgrestore();
  148.   }
  149.  
  150.  
  151.   PSgsave();
  152.  
  153.   PStranslate(XOFFSET, YOFFSET);
  154.  
  155.   ppxunit = 0.88*(bounds.size.width-XOFFSET)/ABS(xmax-xmin);
  156.   ppyunit = 0.88*(bounds.size.height-YOFFSET)/ABS(ymax-ymin);
  157.   
  158.  
  159.   if([contourParam doSetAspectRatio]){
  160.  
  161.     if(ABS(xmax-xmin) >= ABS(ymax-ymin)){
  162.       if(ABS(ymax-ymin)*ppxunit >= 0.88*(bounds.size.height-YOFFSET))
  163.     { ppxunit = ppyunit;} else {ppyunit = ppxunit; } 
  164.     }
  165.     else{  
  166.       if(ABS(xmax-xmin)*ppyunit >= 0.88*(bounds.size.width-XOFFSET))
  167.     { ppyunit = ppxunit;} else {ppxunit = ppyunit; }
  168.     }
  169.   }
  170.  
  171.   if(viewPoint == 1){
  172.     if(xmax > xmin){
  173.       xsave = xmax;
  174.       xmax = xmin;
  175.       xmin = xsave;
  176.       [contourParam resetXmin:xmin];
  177.       [contourParam resetXmax:xmax];
  178.     }
  179.     ppxunit = -ppxunit;
  180.   }
  181.   else{
  182.     if(xmax < xmin){
  183.       xsave = xmax;
  184.       xmax = xmin;
  185.       xmin = xsave;
  186.       [contourParam resetXmin:xmin];
  187.       [contourParam resetXmax:xmax];
  188.     }
  189.   }
  190.  
  191. // try this
  192. //  if(ppxunit >= ppyunit){ppyunit = ppxunit;} else { ppxunit = ppyunit;}
  193.  
  194.   xmin = xmin*ppxunit;    /* drawing is all in pixel coordinates */
  195.   xmax = xmax*ppxunit;
  196.   ymin = ymin*ppyunit;
  197.   ymax = ymax*ppyunit;
  198.  
  199.  
  200.   PStranslate(-xmin, -ymin);
  201.   
  202.   if(clearPlot){
  203.     PSsetlinewidth(0);
  204.  
  205.     NXSetColor([contourParam provideForeGroundColor]);
  206.     
  207.     PSnewpath();        /* draw bounding box */
  208.     PSmoveto(xmin, ymin);
  209.     PSlineto(xmax, ymin);
  210.     PSlineto(xmax, ymax);
  211.     PSlineto(xmin, ymax);
  212.     PSclosepath();
  213.     PSstroke();            /* finish bounding box */
  214.  
  215.     if ([contourParam shouldChangeLabelFont]) {
  216.       newLabelFont =
  217.     [theFontManager convertFont:[theFontManager selFont]];
  218.     }
  219.       if (newLabelFont) {
  220.     labelFont = [Font newFont:[newLabelFont name] 
  221.            size:[newLabelFont pointSize]
  222.            style:[newLabelFont style]
  223.            matrix:NX_IDENTITYMATRIX];
  224.     yhgt = [newLabelFont pointSize];
  225.       }
  226.       else {
  227.     labelFont =
  228.       [Font newFont:"Courier" size:12.0 style:0 matrix:NX_IDENTITYMATRIX];
  229.     yhgt = 12.0;
  230.       }
  231.  
  232.     [labelFont set];
  233.  
  234.     /*  draw unit labels */
  235.     if([contourParam shouldShowUnitsLabel]){
  236.  
  237.       PSmoveto(xmin, ymin - 4.0); /* xmin unit label */
  238.       PSsetdash(pattern0, 0, 0.0);
  239.       PSrlineto(0.0, 4.0);
  240.       PSstroke();
  241.       sprintf(unitLabel, "%10.4g", xmin/ppxunit);
  242.       xwid = [labelFont getWidthOf:unitLabel];
  243.       PSmoveto(xmin - xwid/2.0, ymin - yhgt - 5.0);
  244.       PSshow(unitLabel);
  245.  
  246.       PSmoveto(xmax, ymin - 4.0); /* xmax unit label */
  247.       PSsetdash(pattern0, 0, 0.0);
  248.       PSrlineto(0.0, 4.0);
  249.       PSstroke();
  250.       sprintf(unitLabel, "%10.4g", xmax/ppxunit);
  251.       xwid = [labelFont getWidthOf:unitLabel];
  252.       PSmoveto(xmax - xwid/2.0, ymin - yhgt - 5.0);
  253.       PSshow(unitLabel);
  254.  
  255.       PSmoveto(xmin - 4.0, ymin ); /* ymin unit label */
  256.       PSsetdash(pattern0, 0, 0.0);
  257.       PSrlineto(4.0, 0.0);
  258.       PSstroke();
  259.       sprintf(unitLabel, "%10.4g", ymin/ppyunit);
  260.       xwid = [labelFont getWidthOf:unitLabel];
  261.       PSmoveto(xmin - xwid - 10.0, ymin + 2.0 - yhgt/2.0);
  262.       PSshow(unitLabel);
  263.  
  264.       PSmoveto(xmin - 4.0, ymax ); /* ymax unit label */
  265.       PSsetdash(pattern0, 0, 0.0);
  266.       PSrlineto(4.0, 0.0);
  267.       PSstroke();
  268.       sprintf(unitLabel, "%10.4g", ymax/ppyunit);
  269.       xwid = [labelFont getWidthOf:unitLabel];
  270.       PSmoveto(xmin - xwid - 10.0, ymax + 2.0 - yhgt/2.0);
  271.       PSshow(unitLabel);
  272.  
  273.     }
  274.   }
  275.  
  276.   /* MIN and MAX below in case xmin > xmax  and/or  ymin > ymax. */
  277.   PSrectclip(MIN(xmin,xmax), MIN(ymin,ymax), ABS(xmax-xmin), ABS(ymax-ymin));
  278.   
  279.   if(gridDraw)[self gridAndDraw];
  280.   if(functionDraw)[self contourAndDraw];
  281.   
  282.   PSgrestore();
  283.  
  284.   if(clearPlot){
  285.  
  286.  
  287.     /*  draw contour labels */
  288.     if([contourParam shouldShowContourValues]){
  289.  
  290.       if ([contourParam shouldChangeLabelFont]) {
  291.     newLabelFont =
  292.       [theFontManager convertFont:[theFontManager selFont]];
  293.       }
  294.  
  295.       if (newLabelFont) {
  296.     labelFont = [Font newFont:[newLabelFont name] 
  297.            size:[newLabelFont pointSize]
  298.            style:[newLabelFont style]
  299.            matrix:NX_IDENTITYMATRIX];
  300.     yhgt = [newLabelFont pointSize];
  301.       }
  302.       else {
  303.     labelFont =
  304.       [Font newFont:"Courier" size:12.0 style:0 matrix:NX_IDENTITYMATRIX];
  305.     yhgt = 12.0;
  306.       }
  307.  
  308.       [labelFont set];
  309.  
  310.       number_of_contours = [contourParam provideContourNumber:self];
  311.       if(number_of_contours != 0){
  312.     contour_levels = [contourParam provideContourLevels:self];
  313.  
  314.     sprintf(unitLabel, "%10.6g", contour_levels[0]);
  315.     xwid = [labelFont getWidthOf:unitLabel];
  316.  
  317.     inc_cont = 1;
  318.     if(number_of_contours > 50)inc_cont =(int)(number_of_contours/20);
  319.  
  320.     count_cont = 0;
  321.     for (icont=0; icont < number_of_contours; icont = icont + inc_cont)
  322.       {
  323.         count_cont = count_cont+1;
  324.         switch(lineColor){
  325.         case 0:  [self setDrawColor:NX_LTGRAY]; break;
  326.         case 1:  [self setDrawColor:NX_DKGRAY]; break;
  327.         case 2:  [self setDrawColor:NX_BLACK]; break;
  328.         case 3: 
  329.           h = 0.6666*icont/(float)number_of_contours;
  330.           s = 1.0;
  331.           br = 1.0;
  332.           color = NXConvertHSBToColor(h,s,br);
  333.           NXSetColor(color);
  334.           break;
  335.         }
  336.         sprintf(unitLabel, "%10.6g", contour_levels[icont]);
  337.         PSmoveto(bounds.size.width-xwid-24.,
  338.              bounds.size.height-count_cont*(yhgt+3.0)-40.0);
  339.         PSshow(unitLabel);
  340.       }
  341.     
  342.     if(number_of_contours - count_cont*inc_cont != 0)
  343.       {
  344.         switch(lineColor){
  345.         case 0:  [self setDrawColor:NX_LTGRAY]; break;
  346.         case 1:  [self setDrawColor:NX_DKGRAY]; break;
  347.         case 2:  [self setDrawColor:NX_BLACK]; break;
  348.         case 3: 
  349.           h = 0.6666*1.0;
  350.           s = 1.0;
  351.           br = 0.6;
  352.           color = NXConvertHSBToColor(h,s,br);
  353.           NXSetColor(color);
  354.           break;
  355.         }
  356.         sprintf(unitLabel, "%10.6g", contour_levels[number_of_contours]);
  357.         PSmoveto(bounds.size.width-xwid-8.,
  358.              bounds.size.height-(count_cont+1)*(yhgt+3.0)-40.0);
  359.         PSshow(unitLabel);
  360.       }
  361.       }
  362.     }
  363.   }
  364.  
  365.   return self;
  366. }
  367.  
  368. - contourAndDraw
  369. {
  370.   int colorMap;
  371.   int lineColor =  [contourParam provideContourLineColor];
  372.   function_part function;    /* the struct of our function */
  373.   int number_of_contours;    /* the number of contour levels */
  374.   float *contour_levels;    /* the contour level values */
  375.  
  376.   function = [contourParam provideFunction:self]; /* get function */
  377.  
  378.   number_of_contours = [contourParam provideContourNumber:self];
  379.  
  380.   contour_levels = [contourParam provideContourLevels:self];
  381.  
  382.   if([contourParam doSolidLines])colorMap = 0;
  383.   if(![contourParam doSolidLines])colorMap = 1;
  384.  
  385.   PSsetlinewidth([contourParam provideContourLineThickness]);
  386.  
  387.   switch(lineColor){
  388.   case 0:  [self setDrawColor:NX_LTGRAY]; break;
  389.   case 1:  [self setDrawColor:NX_DKGRAY]; break;
  390.   case 2:  [self setDrawColor:NX_BLACK]; break;
  391.   case 3:  colorMap = 2; if(![contourParam doSolidLines])colorMap = 3; break;
  392.   }
  393.  
  394.   contour_(&function.jmax, &function.kmax, &function.jmax,
  395.        &function.kmax, function.x, function.y, function.f, 
  396.        &number_of_contours, contour_levels, &ppxunit, &ppyunit, &colorMap);
  397.  
  398.   return self;
  399. }
  400.  
  401. - gridAndDraw
  402. {
  403.  
  404.   int i,j,k;
  405.  
  406.   grid_part grid;    /* the struct of our function */
  407.  
  408.   grid = [contourParam provideGrid:self]; /* get grid */
  409.   
  410.   PSsetlinewidth([contourParam provideGridLineThickness]);
  411.   
  412.   NXSetColor([contourParam provideGridLineColor]);
  413.  
  414.  
  415.   /* j family */
  416.   for (k=0; k < grid.kmax; k++){
  417.     i = k*grid.jmax;
  418.     PSnewpath();
  419.     PSmoveto(grid.x[i]*ppxunit, grid.y[i]*ppyunit);
  420.     for (j=1; j < grid.jmax; j++){
  421.       i = k*grid.jmax + j;
  422.       PSlineto(grid.x[i]*ppxunit, grid.y[i]*ppyunit);
  423.     }
  424.     PSstroke();
  425.   }
  426.  
  427.   /* k family */
  428.   for (j=0; j < grid.jmax; j++){
  429.     PSnewpath();
  430.     PSmoveto(grid.x[j]*ppxunit, grid.y[j]*ppyunit);
  431.     for (k=1; k < grid.kmax; k++){
  432.       i = k*grid.jmax + j;
  433.       PSlineto(grid.x[i]*ppxunit, grid.y[i]*ppyunit);
  434.     }
  435.     PSstroke();
  436.   }
  437.  
  438.   return self;
  439. }
  440.  
  441. - doPrinting:sender
  442. {
  443.  
  444. /* to customize print panel */
  445.   id myPrintPanel = [PrintPanel new];
  446.  
  447.   [ [NXApp printInfo] setMarginLeft:72.0 right:72.0 top:72.0 bottom:72.0 ];
  448.  
  449.   if (bounds.size.height > bounds.size.width) { /* portrait mode */
  450.     if (bounds.size.height/bounds.size.width > 9.0/6.5) {
  451.       [ [NXApp printInfo] setScalingFactor: 9.0*72.0/bounds.size.height];
  452.     }
  453.     else {
  454.       [ [NXApp printInfo] setScalingFactor: 6.5*72.0/bounds.size.width];
  455.     }
  456.     [ [NXApp printInfo] setOrientation:NX_PORTRAIT andAdjust:YES ];
  457.   }
  458.   else {            /* landscape mode */
  459.     if (bounds.size.width/bounds.size.height > 9.0/6.5) {
  460.       [ [NXApp printInfo] setScalingFactor: 9.0*72.0/bounds.size.width];
  461.     }
  462.     else {
  463.       [ [NXApp printInfo] setScalingFactor: 6.5*72.0/bounds.size.height];
  464.     }
  465.     [ [NXApp printInfo] setOrientation:NX_LANDSCAPE andAdjust:YES ];
  466.   }
  467.  
  468.   [myPrintPanel setAccessoryView:printColorAccessory];
  469.  
  470.   [self printPSCode:sender];
  471.   return self;
  472. }
  473.  
  474. - mouseDown:(NXEvent *)e{
  475. /*
  476.  * This code taken from the Mandelbrot example in /NextDeveloper (and modified).
  477.  * We implement the mouseDown method so the user can sweep out a section of
  478.  * the view and select that as the current window in which to view the curve(s).
  479.  */
  480.  
  481.   int looping = YES;
  482.   int oldMask;
  483.   NXRect bbox;
  484.   NXPoint startPoint, currPoint;
  485.   float xmin, xmax, ymin, ymax;
  486.   BOOL zooming = [contourParam doZoom];
  487.  
  488.   if (zooming) {
  489.  
  490.     xmin = [contourParam provideXmin] * ppxunit;
  491.     xmax = [contourParam provideXmax] * ppxunit;
  492.     ymin = [contourParam provideYmin] * ppyunit;
  493.     ymax = [contourParam provideYmax] * ppyunit;
  494.   
  495.   
  496.     oldMask =  [window addToEventMask:NX_MOUSEDRAGGEDMASK];
  497.     startPoint = e->location;
  498.     [self convertPoint:&startPoint fromView:nil];
  499.     NXSetRect(&bbox,startPoint.x,startPoint.y,0.0,0.0);
  500.     [self lockFocus];
  501.     while (looping) {
  502.       e=[NXApp getNextEvent:NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK];
  503.       currPoint = e->location;
  504.       [self convertPoint:&currPoint fromView:nil];
  505.       bbox.size.width = (currPoint.x - startPoint.x);
  506.       bbox.size.height = (currPoint.y - startPoint.y);
  507.       /* Normalize bbox to always have positive width and height */
  508.       if (bbox.size.width < 0) {
  509.     bbox.size.width = -bbox.size.width;
  510.     bbox.origin.x   = startPoint.x - bbox.size.width;
  511.       }
  512.       if (bbox.size.height < 0) {
  513.     bbox.size.height = -bbox.size.height;
  514.     bbox.origin.y    = startPoint.y - bbox.size.height;
  515.       }
  516.       /*
  517.        * constrain the box to have the aspect ratio of the view.  Choose
  518.        * whichever dimension is closer to the desired result.
  519.        */
  520.       PSnewinstance();
  521.       if (looping = (e->type == NX_MOUSEDRAGGED)) {
  522.     PSsetinstance(YES);
  523.     NXSetColor([contourParam provideForeGroundColor]);
  524. //    PSsetgray(NX_BLACK);
  525.     NXFrameRect(&bbox);
  526.     PSsetinstance(NO);
  527.       }
  528.     }
  529.  
  530.     [self unlockFocus];
  531.     [window setEventMask:oldMask];
  532.  
  533.     if ((bbox.size.width > 0) && (bbox.size.height > 0)) {
  534.       /* At this point, bbox is in window coordinates.  Convert to curve
  535.        * coordinates based on this view's coordinates and the bounding box.
  536.        */
  537.       
  538.       xmin = xmin + (bbox.origin.x - XOFFSET);
  539.       xmax = xmin + bbox.size.width;
  540.       ymin = ymin + (bbox.origin.y - YOFFSET);
  541.       ymax = ymin + bbox.size.height;
  542.  
  543.       /* save old min/max */
  544.       [contourParam stackOldMinMax:xmin/ppxunit :xmax/ppxunit
  545.                                  :ymin/ppyunit :ymax/ppyunit];
  546.  
  547.       [contourParam resetXmin:xmin/ppxunit];
  548.       [contourParam resetXmax:xmax/ppxunit];
  549.       [contourParam resetYmin:ymin/ppyunit];
  550.       [contourParam resetYmax:ymax/ppyunit];
  551.  
  552.       /*  Call [self display] to force current values of xmin/xmax/ymin/ymax
  553.        *  to take effect (otherwise xmin, etc., get incremented too many times).
  554.        */
  555.       [contourParam drawPlotButton:1];
  556.       [self display];
  557.       [contourParam drawPlotButton:0];
  558.     }
  559.   }
  560.   return self;
  561. }
  562.  
  563.  
  564.  
  565. - initFrame:(const NXRect *)frameRect
  566. {
  567.   [super initFrame:frameRect];
  568.   /* a place to init stuff  thp 6/12/91 */
  569.   return self;
  570. }
  571.  
  572. - saveEPS:sender
  573. {
  574.     id savePanel = [SavePanel new];
  575.     char  *eps_fileName;    // Name of the EPS file for output
  576.  
  577.     [savePanel setTitle:"SAVE EPS FILE"];
  578.     [savePanel setRequiredFileType:"eps"];
  579.     if ([savePanel runModal])  {
  580.       eps_fileName = (char *)calloc(strlen([savePanel filename])+1, 
  581.                     sizeof(char));
  582.       strcpy(eps_fileName, [savePanel filename]);
  583.       [self savePSCode:eps_fileName];
  584.     }
  585.  
  586.     return self;
  587. }
  588.  
  589. - savePSCode:(char *)aFile
  590. {
  591.     NXStream    *psStream;
  592.  
  593.     psStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
  594.     if (!psStream)  {
  595.       return self;
  596.     }
  597.     [self getBounds:&bounds];
  598.     [self copyPSCodeInside:&bounds to:psStream];
  599.        
  600.     NXFlush(psStream);
  601.     NXSaveToFile(psStream, aFile);
  602.     NXCloseMemory(psStream, NX_FREEBUFFER);
  603.  
  604.     return self;
  605. }
  606.  
  607. /*
  608.  * Following code taken from the Graph example in NextDeveloper/Examples.
  609.  *
  610.  * Copies the current view into the Pasteboard as PostScript.
  611.  */
  612. - copyPScode:sender
  613. {
  614.     NXStream *psStream;
  615.     id        pb;
  616.     char     *data;
  617.     int       dataLen, maxDataLen;
  618.  
  619.   /* Open a stream on memory where we will collect the PostScript */
  620.     psStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
  621.     if (!psStream)
  622.       return self;
  623.  
  624.   /* Tell the Pasteboard we're going to copy PostScript */
  625.     pb = [Pasteboard new];
  626.     [pb declareTypes:&NXPostScriptPboardType num:1 owner:self];
  627.  
  628.   /* writes the PostScript for the whole plot as EPS into the stream */
  629.     [self getBounds:&bounds];
  630.     [self copyPSCodeInside:&bounds to:psStream];
  631.  
  632.   /* get the buffered up PostScript out of the stream */
  633.     NXGetMemoryBuffer(psStream, &data, &dataLen, &maxDataLen);
  634.  
  635.   /* put the buffer in the Pasteboard, free the stream (and the buffer) */
  636.     [pb writeType:NXPostScriptPboardType data:data length:dataLen];
  637.     NXCloseMemory(psStream, NX_FREEBUFFER);
  638.     return self;
  639. }
  640.  
  641. @end
  642.